package com.pay.demo.tech.statemachine;

import com.pay.demo.enums.PayStatusChangeEventEnum;
import com.pay.demo.enums.PayStatusEnum;
import com.pay.demo.model.base.PayModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.squirrelframework.foundation.fsm.annotation.StateMachineParameters;
import org.squirrelframework.foundation.fsm.annotation.Transit;
import org.squirrelframework.foundation.fsm.annotation.Transitions;
import org.squirrelframework.foundation.fsm.impl.AbstractUntypedStateMachine;

/**
 * @program: demo
 * @description:
 * @author: guoxh
 * @create: 2019-04-04 13:52
 **/
@Slf4j
@StateMachineParameters(stateType = PayStatusEnum.class, eventType = PayStatusChangeEventEnum.class,
        //StateMachineContext 自定义上下文，用来传递数据
        contextType = PayStateMachineContext.class)
@Transitions({
        //创建订单成功事件
        @Transit(from = "CHUSHI", to = "CHUANGJIAN_DINGDAN_CHENGGONG", on = "CREATE_ORDER_SUCCESSFUL_EVENT", callMethod = "createOrderSuccessfulEvent"),
        //创建订单失败事件
        @Transit(from = "CHUSHI", to = "CHUANGJIAN_DINGDAN_SHIBAI", on = "CREATE_ORDER_FAIL_EVENT"),
        //发送短信成功事件
        @Transit(from = "CHUANGJIAN_DINGDAN_CHENGGONG", to = "FASONG_DUANXIN_CHENGGONG", on = "SEND_SMS_SUCCESSFUL_EVENT"),
        //发送短信失败事件
        @Transit(from = "CHUANGJIAN_DINGDAN_CHENGGONG", to = "FASONG_DUANXIN_SHIBAI", on = "SEND_SMS_FAIL_EVENT"),
        //受理成功事件
        @Transit(from = "FASONG_DUANXIN_CHENGGONG", to = "SHOULI_CHENGGONG", on = "ACCEPT_SUCCESSFUL_EVENT"),
        //受理失败事件
        @Transit(from = "FASONG_DUANXIN_CHENGGONG", to = "SHOULI_SHIBAI", on = "ACCEPT_FAIL_EVENT"),
        //支付成功事件
        @Transit(from = "SHOULI_CHENGGONG", to = "ZHIFU_CHENGGONG", on = "PAY_SUCCESSFUL_EVENT"),
        //支付失败事件
        @Transit(from = "SHOULI_CHENGGONG", to = "ZHIFU_SHIBAI", on = "PAY_FAIL_EVENT"),
})
public class PayStateMachine extends AbstractUntypedStateMachine {
    protected ApplicationContext applicationContext;

    //定义构造函数接受ApplicationContext注入
    public PayStateMachine(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void createOrderSuccessfulEvent(PayStatusEnum fromState, PayStatusEnum toState, PayStatusChangeEventEnum event, PayStateMachineContext context) {
        log.info("创建订单成功事件处理,fromState:{},toState:{},event:{},context:{}", fromState, toState, event, context);
    }

    @Override
    protected void afterTransitionCompleted(Object fromState, Object toState, Object event, Object context) {
        if (context instanceof PayStateMachineContext && toState instanceof PayStatusEnum) {
            //从上下文中获取需要持久化的数据，例如订单ID等
            PayStateMachineContext payStateMachineContext = (PayStateMachineContext) context;
            String serialsNumber = payStateMachineContext.currentInstanceId();
            PayModel payModel = payStateMachineContext.currentInstance(serialsNumber);
            log.info("持久化操作:{}", payModel.getPayTransaction());
            payModel.updateOrderStatus(((PayStatusEnum) toState));
        } else {
            try {
                throw new Exception("type not support, context expect " + PayStateMachineContext.class.getSimpleName()
                        + ", actually " + context.getClass().getSimpleName() + ", state expect "
                        + PayStatusEnum.class.getSimpleName() + ", actually " + toState.getClass().getSimpleName());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
